﻿using Hx.ADSyncPlatform.Common.Log;
using Hx.ADSyncPlatform.InfrastructureSecurity;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Hx.ADSyncPlatform.WebApi.Rpc
{
    public class RpcClient
    {
        private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        public string AccessToken { get; set; }

        private RpcConfig config;

        public RpcClient(RpcConfig rpcConfig)
        {
            this.config = rpcConfig;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private string CreateJwtToken()
        {
            string Issuer = this.config.Jwt.Issuer;
            string audience = this.config.Jwt.Audience;
            TimeSpan expires = TimeSpan.FromMinutes(60);
            SigningCredentials signingCredentials = null;
            //Claim[] claims = new Claim[] { new Claim("gdkey", Guid.NewGuid().ToString()) };
            //Claim[] claims = new Claim[] { new Claim("gdkey", Guid.NewGuid().ToString()),Net };

            var claims = new[] {
                new Claim("gdkey", Guid.NewGuid().ToString()),
                new Claim("exp",DateTimeOffset.UtcNow.AddDays(1).ToUnixTimeMilliseconds().ToString() )
            };
            //Claim[] claims = new Claim[] { new Claim("gdkey", "e23e2ew824d8e524fa130a7") };
            if (this.config.Jwt.Alg == "HS256")
            {
                var keyByteArray = Encoding.ASCII.GetBytes(this.config.Jwt.SecretKey);
                var signingKey = new SymmetricSecurityKey(keyByteArray);
                signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
            }
            //expires: now.Add(expires),
            var now = DateTime.Now;
            // 实例化JwtSecurityToken
            var jwt = new JwtSecurityToken(
                issuer: Issuer,
                audience: audience,
                claims: claims,

                signingCredentials: signingCredentials
            );
            // 生成 Token
            var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

            return encodedJwt;
        }

        private string GenerateRandomNum()
        {
            string serialNum = DateTime.Now.ToString("yyyyMMddHHmmssms");
            Random ra = new Random();
            serialNum += ra.Next(10, 99);
            return serialNum;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="computer"></param>
        /// <returns></returns>
        public RpcResponse SyncComputer(string uid, string computer)
        {
            try
            {
                //uid = "adceshi1";
                this.AccessToken = this.CreateJwtToken();
                logger.Debug("token:" + AccessToken);
                computer = computer.Replace(".", "-");
                Uri serverUri = new Uri(this.config.Host + this.config.Path);
                //string relativePath = "/otcomputer?user_key=" + this.config.UserKey;
                //Uri fullUri = new Uri(serverUri, relativePath);

                var client = new RestClient(serverUri);
                var request = new RestRequest("otcomputer", Method.POST);
                request.AddParameter("user_key", this.config.UserKey, ParameterType.QueryString);
                request.AddHeader("Authorization", "Bearer " + this.AccessToken);
                logger.Debug("UID加密前:" + uid);
                logger.Debug("AesKey:" + this.config.AesKey);
                string excryptedUid = Encrypt.AESEncrypt(uid, this.config.AesKey, this.config.AesIV);
                logger.Debug("uid加密后:" + excryptedUid);
                excryptedUid = System.Web.HttpUtility.UrlEncode(excryptedUid);
                //excryptedUid = Uri.EscapeDataString(excryptedUid);
                var body = new
                {
                    requestId = GenerateRandomNum(),
                    uid = excryptedUid,
                    computer = computer
                };
                request.AddJsonBody(body);
                logger.Debug("[URL]:" + serverUri);
                logger.Debug("[Parameters]:" + JsonConvert.SerializeObject(request.Parameters));
                logger.Debug("[BODY]:" + JsonConvert.SerializeObject(body));

                logger.Debug("uid encode后:" + excryptedUid);
                logger.Debug("computer:" + computer);
                //var response = client.Post(request);
                var restResponse = client.Execute<RpcResponse>(request, Method.POST);
                logger.Debug("原始响应:" + restResponse.Content);
                if (restResponse.IsSuccessful)
                {
                    return restResponse.Data;
                    //< RpcResponse >
                    //try
                    //{
                    //    var rpcResponse = JsonConvert.DeserializeObject<RpcResponse>(restResponse.Content);
                    //    return rpcResponse;
                    //}
                    //catch (Exception ex)
                    //{
                    //    logger.Error(ex, "JSON序列化失败:" + ex.Message);
                    //    return new RpcResponse()
                    //    {
                    //        Code = "500",
                    //        Msg = $"远程接口调用失败,错误信息：{ rawResponse.Content}"
                    //    };
                    //}
                }
                else
                {
                    return new RpcResponse()
                    {
                        Code = "500",
                        Msg = $"远程接口调用失败,错误信息：{ restResponse.Content ?? restResponse.ErrorMessage}"
                    };
                }

            }
            catch (Exception ex)
            {
                logger.Error(ex);
                throw ex;
                //return new RpcResponse()
                //{
                //    Code = "500",
                //    Msg = ex.Message
                //};
            }

        }
    }
}
